home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-03 | 55.2 KB | 2,068 lines |
- Newsgroups: comp.sources.x
- Path: uunet!elroy.jpl.nasa.gov!ames!pasteur!nntp
- From: scott.oaks@East.Sun.COM (Scott Oaks)
- Subject: v15i150: OpenLook Virtual Window Mgr (3.0), Part04/21
- Message-ID: <1992Feb4.135516.6975@pasteur.Berkeley.EDU>
- Sender: dcmartin@msi.com (David C. Martin - Moderator)
- Nntp-Posting-Host: postgres.berkeley.edu
- Organization: University of California, at Berkeley
- References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
- Date: Tue, 4 Feb 1992 13:55:16 GMT
- Approved: dcmartin@msi.com
-
- Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
- Posting-number: Volume 15, Issue 150
- Archive-name: olvwm-3.0/part04
-
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 4 (of 21)."
- # Contents: Imakefile moveresize.c
- # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:42 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Imakefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Imakefile'\"
- else
- echo shar: Extracting \"'Imakefile'\" \(3365 characters\)
- sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
- X/**/# If you want to install the help files for olvwm, set HasInfoFiles to YES
- X#define HasInfoFiles YES
- X
- X/**/# If you need the default menu file (you haven't installed OPENWINDOWS or
- X/**/# you haven't installed olwm) set NeedMenuFile to YES
- X#define NeedMenuFile NO
- X
- X/**/# If you haven't installed olwm from xview3 or from Sun's OpenWindows,
- X/**/# and you want to install the olwm man page (which discusses most of the
- X/**/# window operations), defind NeedOlwmManPage to YES
- X#define NeedOlwmManPage NO
- X
- X#undef DestDir
- X#define DestDir /auto/openwin
- X
- X/**/# No more changes needed
- X
- X#include <XView.tmpl>
- X
- X/**/#########################################################################
- X/**/# @(#)Imakefile 1.5 10/4/91 SMI
- X/**/# Imakefile for olwm release 3.0.
- X
- XDEFINES = -DOW_I18N_L3 -DSUNDAE -DSHAPE
- XINCLUDES = -I$(HEADER_DEST) -I$(TOP)
- XSYS_LIBRARIES = -ll -lm
- XDEPLIBS =
- XLOCAL_LIBRARIES = $(OLGXLIB) $(XLIB)
- X
- XHEADERS = cmdstream.h defaults.h environ.h events.h \
- X gettext.h globals.h group.h helpcmd.h i18n.h \
- X iconimage.h iconmask.h kbdfuncs.h list.h mem.h menu.h \
- X notice.h olcursor.h olgx_impl.h ollocale.h olwm.h \
- X patchlevel.h properties.h resources.h screen.h slots.h\
- X st.h virtual.h win.h
- X
- XINFOFILES = olvwm.info
- X#if NeedOlwmManPage
- XMANPAGES = olwm.man olvwmrc.man
- X#else
- XMANPAGES = olvwmrc.man
- X#endif
- XBITMAPS = iconbitmap.h
- XSCRIPTS =
- XMISC = openwin-menu
- X
- XSRCS = Debug.c Error.c Notice.c Select.c WinInfo.c atom.c \
- X client.c cmdstream.c defaults.c environ.c evbind.c \
- X events.c gettext.c group.c helpsend.c images.c kbdfuncs.c \
- X list.c mem.c menu.c moveresize.c ol_button.c olwm.c olvwmrc.c \
- X properties.c resources.c screen.c services.c slave.c slots.c \
- X st.c states.c usermenu.c usleep.c virtual.c win.c winbusy.c \
- X winbutton.c wincolor.c winframe.c wingframe.c \
- X winicon.c winipane.c winmenu.c winnofoc.c \
- X winpane.c winpinmenu.c winpush.c winresize.c \
- X winroot.c
- X
- XOBJS = \
- X Debug.o Error.o Notice.o Select.o WinInfo.o atom.o \
- X client.o cmdstream.o defaults.o environ.o evbind.o \
- X events.o gettext.o group.o helpsend.o images.o kbdfuncs.o \
- X list.o mem.o menu.o moveresize.o ol_button.o olwm.o olvwmrc.o \
- X properties.o resources.o screen.o services.o slave.o slots.o \
- X st.o states.o usermenu.o usleep.o version.o virtual.o win.o \
- X winbusy.o winbutton.o wincolor.o winframe.o wingframe.o \
- X winicon.o winipane.o winmenu.o winnofoc.o \
- X winpane.o winpinmenu.o winpush.o winresize.o \
- X winroot.o
- X
- X
- XALLFILES = \
- X ${HEADERS} ${BITMAPS} ${SRCS} \
- X ${MISC} ${INFOFILES} ${MANPAGES} ${SCRIPTS}
- X
- XComplexProgramTarget(olvwm)
- X
- X#if NeedMenuFile
- XInstallNonExecList($(MISC),$(LIBRARY_DEST))
- X#endif
- X
- Xparse.c: parse.l
- X lex -t parse.l > parse.c
- X
- Xolvwmrc.c: olvwmrc.y
- X yacc olvwmrc.y
- X mv y.tab.c olvwmrc.c
- X
- Xolvwmrc.o: parse.c olvwmrc.c
- X
- Xversion.c:: ${SRCS} ${HEADERS}
- X @echo -n "#ident \"@(#)olvwm version compiled " > version.c
- X @/bin/sh -c 'echo `date` \"' >> version.c
- X
- Xclean::
- X /bin/rm -f parse.c olvwmrc.c version.c
- X
- Xinstall.man:: $(MANPAGES)
- X @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \
- X else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi
- X @for i in $(MANPAGES) ;\
- X do \
- X echo "installing $$i"; \
- X $(INSTALL) -c $(INSTMANFLAGS) $$i $(DESTDIR)$(MANDIR)/`basename $$i .man`.$(MANSUFFIX) ; \
- X done
- X
- X#include <XView.prog>
- END_OF_FILE
- if test 3365 -ne `wc -c <'Imakefile'`; then
- echo shar: \"'Imakefile'\" unpacked with wrong size!
- fi
- # end of 'Imakefile'
- fi
- if test -f 'moveresize.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'moveresize.c'\"
- else
- echo shar: Extracting \"'moveresize.c'\" \(48613 characters\)
- sed "s/^X//" >'moveresize.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
- X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
- X * file for terms of the license.
- X */
- X
- X#ident "@(#)moveresize.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)moveresize.c 26.37 91/09/14 SMI"
- X *
- X */
- X
- X#include <errno.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <X11/Xos.h>
- X#include <X11/Xlib.h>
- X#include <X11/Xutil.h>
- X#include <X11/keysym.h>
- X
- X#include "i18n.h"
- X#include "ollocale.h"
- X#include "mem.h"
- X#include "olwm.h"
- X#include "win.h"
- X#include "events.h"
- X#include "list.h"
- X#include "globals.h"
- X#include "group.h"
- X#include "virtual.h"
- X
- X/* REMIND - find out how to get rid of this */
- Xextern int Resize_width, Resize_height;
- X
- X#ifdef ALLPLANES
- Xextern int allplanes;
- X#endif
- X
- X
- Xtypedef enum {
- X Unconstrained, /* resizing not constrained */
- X EitherConstrained, /* constrained, but no direction yet */
- X HorizConstrained, /* constrained horizontally */
- X VertConstrained, /* constrained vertically */
- X} Constraint;
- X
- X
- X#define DELTA_INCREASE (1)
- X#define DELTA_DECREASE (-1)
- X#define JUMP_INCREASE (10)
- X#define JUMP_DECREASE (-10)
- X
- X#define REDUCE_ROUNDER 5
- X#define REDUCE_DIVIDER 10
- X
- X/*
- X * drawDouble
- X *
- X * Draw a thick box on the given window, using the given GC. The box is drawn
- X * using four rectangles. This technique is used instead of wide lines
- X * because this routine is used during animation, and the wide line code of
- X * some servers is too slow.
- X */
- X
- X#define defrect(r, X, Y, W, H) \
- X (r).x = X, (r).y = Y, (r).width = W, (r).height = H
- X
- Xstatic void
- XdrawDouble(dpy, win, gc, x, y, w, h)
- X Display *dpy;
- X Window win;
- X GC gc;
- X int x, y, w, h;
- X{
- X register int thick = GRV.RubberBandThickness;
- X XRectangle rects[4];
- X int nrects,doublethick;
- X
- X if (w == 0 && h == 0)
- X return;
- X
- X doublethick = 2 * thick;
- X
- X /* if too small for box just draw one solid rect */
- X if (w <= doublethick || h <= doublethick) {
- X defrect(rects[0], x, y, w, h);
- X nrects = 1;
- X /* else draw all 4 rects for the box */
- X } else {
- X defrect(rects[0], x, y, w, thick);
- X defrect(rects[1], x, y + h - thick, w, thick);
- X defrect(rects[2], x, y + thick, thick, h - doublethick);
- X defrect(rects[3], x + w - thick, y + thick, thick, h - doublethick);
- X nrects = 4;
- X }
- X#ifdef ALLPLANES
- X if (allplanes)
- X XAllPlanesFillRectangles(dpy, win, rects, nrects);
- X else
- X#endif /* ALLPLANES */
- X XFillRectangles(dpy, win, gc, rects, nrects);
- X}
- X
- X#undef defrect
- X
- X
- X/* ===== status window ==================================================== */
- X
- X
- X#define HMARGIN 5
- X#define VMARGIN 3
- X
- X
- Xtypedef struct {
- X Display *dpy;
- X Window win;
- X int ypos;
- X int width;
- X int height;
- X XFontStruct *font;
- X ScreenInfo *scrinfo;
- X} StatusWinInfo;
- X
- X
- Xstatic StatusWinInfo *
- XcreateStatusWindow(dpy, scrinfo, proto)
- X Display *dpy;
- X ScreenInfo *scrinfo;
- X char *proto;
- X{
- X int width, height;
- X XSetWindowAttributes attr;
- X StatusWinInfo *sw;
- X int changed, x, y, w, h;
- X
- X sw = MemNew(StatusWinInfo);
- X sw->dpy = dpy;
- X sw->font = GRV.TitleFontInfo;
- X sw->height = sw->font->ascent + sw->font->descent + 2*VMARGIN;
- X sw->width = XTextWidth(sw->font, proto, strlen(proto)) + 2*HMARGIN;
- X sw->scrinfo = scrinfo;
- X
- X if (MatchString(GRV.ResizePosition, "center")) {
- X x = (DisplayWidth(dpy, scrinfo->screen) - sw->width) / 2;
- X y = (DisplayHeight(dpy, scrinfo->screen) - sw->height) / 2;
- X }
- X else {
- X changed = XParseGeometry(GRV.ResizePosition, &x, &y, &w, &h);
- X if (changed & XValue)
- X if (changed & XNegative)
- X x = DisplayWidth(dpy, scrinfo->screen) + x;
- X else ;
- X else x = 0;
- X if (changed & YValue)
- X if (changed & YNegative)
- X y = DisplayHeight(dpy, scrinfo->screen) + y;
- X else ;
- X else y = 0;
- X }
- X
- X attr.border_pixel = 0;
- X attr.colormap = scrinfo->colormap;
- X attr.save_under = True;
- X sw->win = XCreateWindow(dpy, scrinfo->rootid,
- X x, y, sw->width, sw->height, 0,
- X scrinfo->depth, InputOutput, scrinfo->visual,
- X CWColormap | CWBorderPixel | CWSaveUnder, &attr);
- X XMapRaised(dpy, sw->win);
- X sw->ypos = VMARGIN + sw->font->ascent;
- X return sw;
- X}
- X
- X
- Xstatic void
- XpaintStatusWindow(sw, string)
- X StatusWinInfo *sw;
- X char *string;
- X{
- X if (sw == NULL)
- X return;
- X
- X olgx_draw_box(sw->scrinfo->gi[NORMAL_GINFO], sw->win, 0, 0,
- X sw->width, sw->height, OLGX_NORMAL | OLGX_ERASE, True);
- X
- X XDrawString(sw->dpy, sw->win, sw->scrinfo->gc[FOREGROUND_GC],
- X (sw->width - XTextWidth(sw->font, string, strlen(string))) / 2,
- X sw->ypos, string, strlen(string));
- X}
- X
- X
- Xstatic void
- XdestroyStatusWindow(sw)
- X StatusWinInfo *sw;
- X{
- X if (sw == NULL)
- X return;
- X
- X XDestroyWindow(sw->dpy, sw->win);
- X MemFree(sw);
- X}
- X
- X
- X/* ===== mouse-based window moving ======================================== */
- X
- X
- Xtypedef struct {
- X Display *dpy;
- X int initX, initY;
- X int offX, offY;
- X int curX, curY;
- X int rounder, divider;
- X List *winlist;
- X WinGenericFrame *frame;
- X StatusWinInfo *statuswindow;
- X Constraint constraint;
- X Bool dragwin; /* true=dragwin, false=dragframe */
- X Bool mouse;
- X Bool AutoRaise; /* orig value of autoraise */
- X/*
- X * Virtual Desktop things
- X */
- X int check_vdm;
- X int vdm_screenX;
- X int vdm_screenY;
- X int inVDM;
- X VirtualDesktop *vdm;
- X int targetScreenX;
- X int targetScreenY;
- X Region region;
- X Window *children;
- X int num_children;
- X int vdm_stacking_order;
- X} MoveClosure;
- X
- X
- Xstatic Bool movewinInterposer();
- Xstatic void *moveOneWindow();
- Xstatic void *configOneWindow();
- Xstatic void *drawOneBox();
- Xstatic void moveDone();
- X
- X
- Xstatic void
- XmouseMovePaintStatus(mstuff, x, y)
- X MoveClosure *mstuff;
- X int x, y;
- X{
- X char buf[50];
- X
- X sprintf(buf, gettext("location: %d , %d"), x, y);
- X paintStatusWindow(mstuff->statuswindow, buf);
- X}
- X
- Xstatic int
- XgetWindowStackingOrder(win, mstuff)
- X Window win;
- X MoveClosure *mstuff;
- X{
- Xint i;
- X
- X for (i = 0; i < mstuff->num_children; i++)
- X if (mstuff->children[i] == win)
- X return i;
- X return 0;
- X}
- X
- Xstatic void *
- XmoveAddRegion(cli, mstuff)
- X Client *cli;
- X MoveClosure *mstuff;
- X
- X{
- XRegion new;
- XXRectangle rect;
- Xint stacking_order;
- X
- X if (!cli->framewin)
- X return NULL;
- X if (PANEWINOFCLIENT(cli) == PANEWINOFCLIENT(mstuff->vdm->client))
- X return NULL;
- X if (cli->screen != mstuff->vdm->client->screen)
- X return NULL;
- X switch(cli->wmState) {
- X case IconicState:
- X if (getWindowStackingOrder(cli->iconwin->core.self, mstuff) <
- X mstuff->vdm_stacking_order)
- X return NULL;
- X rect.x = cli->iconwin->core.x;
- X rect.y = cli->iconwin->core.y;
- X rect.width = cli->iconwin->core.width;
- X rect.height = cli->iconwin->core.height;
- X break;
- X case NormalState:
- X if (getWindowStackingOrder(cli->framewin->core.self, mstuff) <
- X mstuff->vdm_stacking_order)
- X return NULL;
- X rect.x = cli->framewin->core.x;
- X rect.y = cli->framewin->core.y;
- X rect.width = cli->framewin->core.width;
- X rect.height = cli->framewin->core.height;
- X break;
- X default:
- X return NULL;
- X }
- X new = XCreateRegion();
- X XUnionRectWithRegion(rect, new, new);
- X XSubtractRegion(mstuff->region, new, mstuff->region);
- X XDestroyRegion(new);
- X return NULL;
- X}
- X
- X/*
- X * UserMoveWindows
- X *
- X * Allow the user to move a window or the set of selected windows. The
- X * "first" parameter must be the button event that initiated the interaction.
- X * The "winInfo" parameter must be the frame or icon on which the action was
- X * initiated. The external boolean DragWindow controls whether the whole
- X * window is moved or whether the outline is moved.
- X *
- X * TODO:
- X * (1) clean up coordinate systems;
- X * (2) implement hysteresis against other windows' edges.
- X */
- Xvoid
- XUserMoveWindows(cli, first)
- X Client *cli;
- X XEvent *first;
- X{
- X Display *dpy = cli->dpy;
- X List *winlist = NULL_LIST;
- X static MoveClosure mstuff;
- X Time timestamp;
- X XRectangle rect;
- X int dummy;
- X
- X {
- X /*
- X * Set up where the VDM is to allow/prevent moving into it
- X */
- X VirtualDesktop *vdm;
- X unsigned int x, y, w, h, bw, d;
- X Window root;
- X
- X vdm = cli->scrInfo->vdm;
- X if (vdm && vdm->client->wmState != IconicState &&
- X vdm->client != cli && GRV.AllowMoveIntoDesktop) {
- X mstuff.check_vdm = True;
- X XGetGeometry(dpy, vdm->client->framewin->core.self,
- X &root, &x, &y, &w, &h, &bw, &d);
- X mstuff.vdm_screenX = x;
- X mstuff.vdm_screenY = y;
- X XGetGeometry(dpy, vdm->client->framewin->fcore.panewin->core.self,
- X &root, &x, &y, &w, &h, &bw, &d);
- X mstuff.vdm_screenX += x;
- X mstuff.vdm_screenY += y;
- X mstuff.vdm = vdm;
- X rect.x = mstuff.vdm_screenX;
- X rect.y = mstuff.vdm_screenY;
- X rect.width = w;
- X rect.height = h;
- X }
- X else mstuff.check_vdm = False;
- X mstuff.vdm = vdm;
- X }
- X
- X mstuff.dpy = dpy;
- X mstuff.offX = 0;
- X mstuff.offY = 0;
- X mstuff.constraint = Unconstrained;
- X mstuff.rounder = 0;
- X mstuff.divider = 1;
- X /*
- X * Disable Autoraise while dragging -- otherwise, we obscure the moveresize
- X * box
- X */
- X mstuff.AutoRaise = GRV.AutoRaise;
- X GRV.AutoRaise = False;
- X TimeoutCancel();
- X
- X if (cli->wmState == IconicState)
- X mstuff.frame = (WinGenericFrame *) cli->iconwin;
- X else
- X mstuff.frame = (WinGenericFrame *) cli->framewin;
- X
- X if (first == NULL || first->type == KeyPress) {
- X timestamp = (first == NULL) ? CurrentTime : first->xkey.time;
- X mstuff.dragwin = False;
- X mstuff.curX = mstuff.initX = mstuff.frame->core.x;
- X mstuff.curY = mstuff.initY = mstuff.frame->core.y;
- X mstuff.mouse = False;
- X } else {
- X /* it's a ButtonPress */
- X
- X mstuff.curX = mstuff.initX = first->xbutton.x_root;
- X mstuff.curY = mstuff.initY = first->xbutton.y_root;
- X mstuff.dragwin = GRV.DragWindow;
- X mstuff.mouse = True;
- X timestamp = first->xbutton.time;
- X
- X if (first->xbutton.state & ModMaskMap[MOD_INVERT])
- X mstuff.dragwin = !mstuff.dragwin;
- X
- X if (first->xbutton.state & ModMaskMap[MOD_REDUCE]) {
- X mstuff.rounder = REDUCE_ROUNDER;
- X mstuff.divider = REDUCE_DIVIDER;
- X }
- X
- X if (first->xbutton.state & ModMaskMap[MOD_CONSTRAIN])
- X mstuff.constraint = EitherConstrained;
- X }
- X /*
- X * This is esoteric: we don't want to allow a drag into an obscured
- X * part of the VDM. If we're dragging the outline, then it's easy,
- X * since each event has the dest window, which will be the VDM only
- X * when we want it to be. If we're dragging the window, then the window
- X * in the event will be the window's frame, and we have to have another
- X * test to see if we're over an unobscured part of the VDM.
- X *
- X * The best I can come up with now is to create a region equal to the
- X * unobscured part of the VDM. This is probably very slow.
- X */
- X if (mstuff.check_vdm) {
- X if (mstuff.dragwin) {
- X mstuff.region = XCreateRegion();
- X /* rect is set up above */
- X XUnionRectWithRegion(rect, mstuff.region, mstuff.region);
- X if (!XQueryTree(dpy, WinRootID(mstuff.frame), &dummy, &dummy,
- X &mstuff.children, &mstuff.num_children))
- X mstuff.num_children = 0;
- X mstuff.vdm_stacking_order =
- X getWindowStackingOrder(mstuff.vdm->client->framewin->core.self,
- X mstuff);
- X ListApply(ActiveClientList, moveAddRegion, &mstuff);
- X }
- X else mstuff.region = NULL;
- X }
- X
- X /*
- X * Generate the list of windows to be moved. If the initial window is
- X * selected, we're moving the selection; otherwise, we're moving just this
- X * window.
- X */
- X if (IsSelected(cli)) {
- X Client *c = (Client *) 0;
- X int allsticky = True;
- X
- X while (c = EnumSelections(c)) {
- X if (c->wmState == IconicState)
- X winlist = ListCons(c->iconwin, winlist);
- X else
- X winlist = ListCons(c->framewin, winlist);
- X /*
- X * Can't move sticky windows into the VDM. Thus, if all windows
- X * is sticky, we don't allow any move into the VDM, since otherwise
- X * its too confusing
- X */
- X allsticky = allsticky & !c->sticky;
- X }
- X if (allsticky)
- X mstuff.check_vdm = False;
- X } else {
- X winlist = ListCons(mstuff.frame, NULL_LIST);
- X if (cli->sticky)
- X mstuff.check_vdm = False;
- X }
- X mstuff.winlist = winlist;
- X
- X /* Grab the pointer to change the cursor and confine to the root window. */
- X
- X if (XGrabPointer(dpy, cli->scrInfo->rootid, True,
- X ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
- X GrabModeAsync, GrabModeAsync, cli->scrInfo->rootid,
- X GRV.MovePointer, timestamp) != GrabSuccess)
- X {
- X ErrorWarning(gettext("failed to grab pointer"));
- X return;
- X }
- X
- X if (XGrabKeyboard(dpy, cli->scrInfo->rootid, False,
- X GrabModeAsync, GrabModeAsync,
- X timestamp) != GrabSuccess)
- X {
- X /* note: not fatal */
- X ErrorWarning(gettext("failed to grab keyboard"));
- X }
- X
- X InstallInterposer(movewinInterposer, &mstuff);
- X
- X if (GRV.ShowMoveGeometry)
- X mstuff.statuswindow = createStatusWindow(dpy, cli->scrInfo,
- X gettext("location: 0000 , 0000"));
- X else
- X mstuff.statuswindow = NULL;
- X
- X /*
- X * If we're dragging the outlines, we must also grab the server and draw
- X * the initial set of bounding boxes.
- X */
- X if (!mstuff.dragwin) {
- X XGrabServer(dpy);
- X (void) ListApply(mstuff.winlist, drawOneBox, &mstuff);
- X }
- X}
- X
- X
- Xvoid
- XmoveUpdate(mstuff, event)
- X MoveClosure *mstuff;
- X XEvent *event;
- X{
- X if (!mstuff->dragwin)
- X (void) ListApply(mstuff->winlist, drawOneBox, mstuff);
- X
- X if (mstuff->check_vdm && event) {
- X if (!mstuff->region) {
- X if (event->xmotion.window == PANEWINOFCLIENT(mstuff->vdm->client))
- X mstuff->inVDM = True;
- X /*
- X * The events on the virtual windows are reported relative to
- X * themselves; so if its a virtual window, we're in the VDM
- X */
- X else if (VGetInfo(event->xmotion.window))
- X mstuff->inVDM = True;
- X else if (mstuff->dragwin) {
- X /*
- X * If we're dragging the window and the event is on the window's
- X * frame (ie we moved just a little) see if we're over the vdm.
- X * If so, move into the vdm
- X */
- X }
- X else mstuff->inVDM = False;
- X }
- X else mstuff->inVDM = XPointInRegion(mstuff->region,
- X event->xmotion.x_root, event->xmotion.y_root);
- X }
- X else mstuff->inVDM = False;
- X
- X if (mstuff->inVDM) {
- X mstuff->offX = (mstuff->curX - mstuff->vdm_screenX) *
- X (mstuff->vdm->resources->scale / mstuff->divider) -
- X mstuff->initX + mstuff->vdm->offsetX;
- X mstuff->offY = (mstuff->curY - mstuff->vdm_screenY) *
- X (mstuff->vdm->resources->scale / mstuff->divider) -
- X mstuff->initY + mstuff->vdm->offsetY;
- X }
- X else {
- X mstuff->offX =
- X (mstuff->curX - mstuff->initX + mstuff->rounder) / mstuff->divider;
- X mstuff->offY =
- X (mstuff->curY - mstuff->initY + mstuff->rounder) / mstuff->divider;
- X }
- X
- X if (mstuff->constraint == EitherConstrained) {
- X if (ABS(mstuff->offX) > ABS(mstuff->offY))
- X mstuff->constraint = HorizConstrained;
- X else
- X mstuff->constraint = VertConstrained;
- X }
- X
- X if (mstuff->constraint == HorizConstrained) {
- X mstuff->offY = 0;
- X } else if (mstuff->constraint == VertConstrained) {
- X mstuff->offX = 0;
- X }
- X
- X if (mstuff->dragwin)
- X (void) ListApply(mstuff->winlist, moveOneWindow, mstuff);
- X else
- X (void) ListApply(mstuff->winlist, drawOneBox, mstuff);
- X}
- X
- X
- Xvoid
- XmoveKeyDelta(mstuff, dx, dy)
- X MoveClosure *mstuff;
- X int dx, dy;
- X{
- X mstuff->constraint = Unconstrained;
- X
- X if (mstuff->mouse) {
- X mstuff->initX -= dx;
- X mstuff->initY -= dy;
- X } else {
- X mstuff->curX += dx;
- X mstuff->curY += dy;
- X }
- X moveUpdate(mstuff, NULL);
- X}
- X
- X
- X/*
- X * movewinInterposer
- X *
- X * Interposer function for moving windows. Moves the list of windows on each
- X * MotionNotify; releases interposition on ButtonRelease.
- X */
- X/*ARGSUSED*/
- Xstatic int
- XmovewinInterposer(dpy, event, w, mstuff)
- X Display *dpy;
- X XEvent *event;
- X WinGeneric *w;
- X MoveClosure *mstuff;
- X{
- X XEvent nextevent;
- X SemanticAction action;
- X
- X switch (event->type) {
- X case ButtonPress:
- X /* ignore if buttons are already down */
- X if (!FirstButtonDown(event))
- X break;
- X
- X switch (ResolveMouseBinding(dpy, event,
- X ModMaskMap[MOD_REDUCE] | ModMaskMap[MOD_CONSTRAIN]))
- X {
- X case ACTION_SELECT:
- X mstuff->mouse = True;
- X mstuff->curX = event->xbutton.x_root;
- X mstuff->curY = event->xbutton.y_root;
- X mstuff->initX = mstuff->curX - mstuff->offX;
- X mstuff->initY = mstuff->curY - mstuff->offY;
- X
- X if (event->xbutton.state & ModMaskMap[MOD_REDUCE]) {
- X mstuff->rounder = REDUCE_ROUNDER;
- X mstuff->divider = REDUCE_DIVIDER;
- X }
- X
- X if (event->xbutton.state & ModMaskMap[MOD_CONSTRAIN])
- X mstuff->constraint = EitherConstrained;
- X break;
- X
- X default: /* otherwise, abort the move operation */
- X mstuff->curX = mstuff->initX;
- X mstuff->curY = mstuff->initY;
- X moveUpdate(mstuff, event);
- X moveDone(mstuff);
- X }
- X break;
- X
- X case ButtonRelease:
- X if (AllButtonsUp(event))
- X moveDone(mstuff);
- X break;
- X
- X case MotionNotify:
- X /* if the event is off the screen, ignore it */
- X if (!event->xmotion.same_screen)
- X break;
- X
- X if (!mstuff->mouse)
- X break;
- X
- X /*
- X * Motion compression. If the next event is a MotionNotify,
- X * ignore this one.
- X */
- X if (XEventsQueued(dpy, QueuedAfterReading) > 0 &&
- X (XPeekEvent(dpy,&nextevent), nextevent.type == MotionNotify))
- X break;
- X
- X mstuff->curX = event->xmotion.x_root;
- X mstuff->curY = event->xmotion.y_root;
- X moveUpdate(mstuff, event);
- X break;
- X
- X case KeyPress:
- X action = FindKeyboardAction(dpy, event);
- X
- X switch (action) {
- X case ACTION_UP:
- X moveKeyDelta(mstuff,0,DELTA_DECREASE);
- X break;
- X case ACTION_DOWN:
- X moveKeyDelta(mstuff,0,DELTA_INCREASE);
- X break;
- X case ACTION_LEFT:
- X moveKeyDelta(mstuff,DELTA_DECREASE,0);
- X break;
- X case ACTION_RIGHT:
- X moveKeyDelta(mstuff,DELTA_INCREASE,0);
- X break;
- X case ACTION_JUMP_UP:
- X moveKeyDelta(mstuff,0,JUMP_DECREASE);
- X break;
- X case ACTION_JUMP_DOWN:
- X moveKeyDelta(mstuff,0,JUMP_INCREASE);
- X break;
- X case ACTION_JUMP_LEFT:
- X moveKeyDelta(mstuff,JUMP_DECREASE,0);
- X break;
- X case ACTION_JUMP_RIGHT:
- X moveKeyDelta(mstuff,JUMP_INCREASE,0);
- X break;
- X case ACTION_EXEC_DEFAULT:
- X moveDone(mstuff);
- X break;
- X case ACTION_STOP:
- X mstuff->curX = mstuff->initX;
- X mstuff->curY = mstuff->initY;
- X moveUpdate(mstuff, NULL);
- X moveDone(mstuff);
- X break;
- X
- X default:
- X if (FindModifierMask(event->xkey.keycode) ==
- X ModMaskMap[MOD_CONSTRAIN])
- X {
- X if (mstuff->mouse) {
- X mstuff->constraint = EitherConstrained;
- X moveUpdate(mstuff, NULL);
- X }
- X } else {
- X KeyBeep(dpy, event);
- X }
- X break;
- X }
- X break;
- X
- X case KeyRelease:
- X if (FindModifierMask(event->xkey.keycode) ==
- X ModMaskMap[MOD_CONSTRAIN])
- X {
- X mstuff->constraint = Unconstrained;
- X moveUpdate(mstuff, NULL);
- X }
- X break;
- X
- X /* Send out expose's immediately */
- X case Expose:
- X return DISPOSE_DISPATCH;
- X
- X default:
- X return DISPOSE_DEFER;
- X }
- X
- X return DISPOSE_USED;
- X}
- X
- X/* windowOff -- function to determine how far a window should be offset
- X * given a pointer offset. Returns both X and Y, by reference.
- X */
- Xstatic void
- XwindowOff(win, mstuff, pox, poy)
- XWinGenericFrame *win;
- XMoveClosure *mstuff;
- Xint *pox, *poy;
- X{
- X int pixw = DisplayWidth(win->core.client->dpy, win->core.client->screen);
- X int hpoint;
- X int pixy = DisplayHeight(win->core.client->dpy, win->core.client->screen);
- X
- X if (mstuff->offX == 0)
- X {
- X *pox = 0;
- X }
- X else if (mstuff->offX > 0)
- X {
- X hpoint = pixw - win->core.x - win->core.width;
- X if (!mstuff->inVDM && (mstuff->offX >= hpoint) &&
- X (mstuff->offX <= hpoint + GRV.EdgeThreshold))
- X *pox = hpoint;
- X else {
- X hpoint = mstuff->vdm->absoluteWidth + mstuff->vdm->offsetX -
- X win->core.x - win->core.width;
- X if (mstuff->offX >= hpoint + win->core.width - Resize_width)
- X *pox = hpoint + win->core.width - Resize_width;
- X else
- X *pox = mstuff->offX;
- X }
- X }
- X else if (mstuff->offX < 0)
- X {
- X if (!mstuff->inVDM && (mstuff->offX <= -win->core.x) &&
- X (mstuff->offX >= (-win->core.x - GRV.EdgeThreshold)))
- X *pox = -win->core.x;
- X else if (mstuff->offX <= (-win->core.x - win->core.width +
- X Resize_width + mstuff->vdm->offsetX))
- X *pox = (-win->core.x - win->core.width +
- X Resize_width + mstuff->vdm->offsetX);
- X else
- X *pox = mstuff->offX;
- X }
- X
- X if (mstuff->offY == 0)
- X {
- X *poy = 0;
- X }
- X else if (mstuff->offY > 0)
- X {
- X hpoint = pixy - win->core.y - win->core.height;
- X if (!mstuff->inVDM && (mstuff->offY >= hpoint) &&
- X (mstuff->offY <= hpoint + GRV.EdgeThreshold))
- X *poy = hpoint;
- X else {
- X hpoint = mstuff->vdm->absoluteHeight + mstuff->vdm->offsetY -
- X win->core.y - win->core.height;
- X if (mstuff->offY >= hpoint + win->core.height - Resize_height)
- X *poy = hpoint + win->core.height - Resize_height;
- X else
- X *poy = mstuff->offY;
- X }
- X }
- X else if (mstuff->offY < 0)
- X {
- X if (!mstuff->inVDM && (mstuff->offY <= -win->core.y) &&
- X (mstuff->offY >= (-win->core.y - GRV.EdgeThreshold)))
- X *poy = -win->core.y;
- X else if (mstuff->offY <= (-win->core.y - win->core.height +
- X Resize_height + mstuff->vdm->offsetY))
- X *poy = (-win->core.y - win->core.height + Resize_height +
- X mstuff->vdm->offsetY);
- X else
- X *poy = mstuff->offY;
- X }
- X}
- X
- X/*
- X * moveOneWindow
- X *
- X * Apply function for window moving animation. Draws a window outline or
- X * actually moves the window, depending on DragWindow.
- X */
- Xstatic void *
- XmoveOneWindow(win, mstuff)
- X WinGenericFrame *win;
- X MoveClosure *mstuff;
- X{
- X int offX, offY;
- X
- X windowOff(win, mstuff, &offX, &offY);
- X XMoveWindow(mstuff->dpy, win->core.self,
- X win->core.x + offX,
- X win->core.y + offY);
- X XMoveWindow(mstuff->dpy, win->core.virtual,
- X (win->core.x + offX - mstuff->vdm->offsetX) /
- X mstuff->vdm->resources->scale,
- X (win->core.y + offY - mstuff->vdm->offsetY) /
- X mstuff->vdm->resources->scale);
- X if (win == mstuff->frame)
- X mouseMovePaintStatus(mstuff, win->core.x + offX, win->core.y + offY);
- X return (void *) 0;
- X}
- X
- X
- X/*
- X * drawOneBox
- X *
- X * Apply function for drawing XOR boxes. Draws a double-width rectangle
- X * around the outline of a single window.
- X */
- Xstatic void *
- XdrawOneBox(w, mstuff)
- X WinGenericFrame *w;
- X MoveClosure *mstuff;
- X{
- X int offX, offY;
- X
- X windowOff(w, mstuff, &offX, &offY);
- X drawDouble(mstuff->dpy, w->core.client->scrInfo->rootid, WinGC(w,ROOT_GC),
- X w->core.x + offX, w->core.y + offY,
- X w->core.width, w->core.height);
- X drawDouble(mstuff->dpy, PANEWINOFCLIENT(mstuff->vdm->client),
- X WinGC(w, ROOT_GC),
- X (w->core.x + offX - mstuff->vdm->offsetX) /
- X mstuff->vdm->resources->scale,
- X (w->core.y + offY - mstuff->vdm->offsetY) /
- X mstuff->vdm->resources->scale,
- X w->core.width / mstuff->vdm->resources->scale,
- X w->core.height / mstuff->vdm->resources->scale);
- X
- X if (w == mstuff->frame)
- X mouseMovePaintStatus(mstuff, w->core.x + offX, w->core.y + offY);
- X
- X return (void *) 0;
- X}
- X
- X
- X/*
- X * doconfigOneWindow
- X *
- X * Apply function for calling a moved window's configfunc.
- X *
- X */
- Xstatic void *
- XdoConfigOneWindow(win, mstuff)
- X WinGenericFrame *win;
- X MoveClosure *mstuff;
- X{
- X int offX, offY;
- X int dw, dh;
- X
- X if (ListIsAMember(win, mstuff->winlist)) {
- X windowOff(win, mstuff, &offX, &offY);
- X GFrameSetConfig(win, win->core.x + offX, win->core.y + offY,
- X win->core.width, win->core.height);
- X }
- X else {
- X /* Else we're moving a dependent window without having selected it --
- X * ie VirtualMoveGroup is True and we're moving into the VDM. So
- X * keep the relative screen position of this window
- X */
- X dw = DisplayWidth(win->core.client->dpy, win->core.client->screen);
- X dh = DisplayHeight(win->core.client->dpy, win->core.client->screen);
- X offX = mstuff->targetScreenX * dw + mstuff->vdm->offsetX;
- X offY = mstuff->targetScreenY * dh + mstuff->vdm->offsetY;
- X GFrameSetConfig(win, (win->core.x % dw) + offX, (win->core.y % dh) + offY,
- X win->core.width, win->core.height);
- X }
- X if (GRV.VirtualRaiseOnMove)
- X RaiseWindow(win);
- X return (void *) 0;
- X}
- X
- Xstatic void *
- XconfigOneClient(cli, mstuff)
- X Client *cli;
- X MoveClosure *mstuff;
- X
- X{
- X doConfigOneWindow(cli->framewin, mstuff);
- X doConfigOneWindow(cli->iconwin, mstuff);
- X cli->flags |= CLMoved;
- X return (void *) 0;
- X}
- X
- Xstatic void *
- XconfigOneWindow(win, mstuff)
- X WinGenericFrame *win;
- X MoveClosure *mstuff;
- X{
- Xint dw, dh;
- Xint offX, offY;
- Xint newScreenX, curScreenX, newScreenY, curScreenY;
- Xint width, height;
- XClient *leader;
- X
- X if (win->core.client->flags & CLMoved)
- X return (void *) 0;
- X dw = DisplayWidth(win->core.client->dpy, win->core.client->screen);
- X dh = DisplayHeight(win->core.client->dpy, win->core.client->screen);
- X windowOff(win, mstuff, &offX, &offY);
- X width = win->core.width;
- X height = win->core.height;
- X if (GRV.VirtualMoveGroups) {
- X switch(win->core.client->groupmask) {
- X case GROUP_LEADER:
- X leader = win->core.client;
- X break;
- X case GROUP_DEPENDENT:
- X leader = GroupLeader(win->core.client->groupid);
- X if (!leader) {
- X doConfigOneWindow(win, mstuff);
- X return (void *) 0;
- X }
- X break;
- X case GROUP_INDEPENDENT:
- X doConfigOneWindow(win, mstuff);
- X return (void *) 0;
- X }
- X curScreenX = (win->core.x - mstuff->vdm->offsetX) / dw;
- X if (offX < 0)
- X newScreenX = (win->core.x + offX + mstuff->vdm->offsetX) / dw;
- X else newScreenX = (win->core.x + offX - mstuff->vdm->offsetX) / dw;
- X mstuff->targetScreenX = newScreenX;
- X curScreenY = (win->core.y - mstuff->vdm->offsetY) / dh;
- X if (offY < 0)
- X newScreenY = (win->core.y + offY + mstuff->vdm->offsetY) / dh;
- X else newScreenY = (win->core.y + offY - mstuff->vdm->offsetY) / dh;
- X mstuff->targetScreenY = newScreenY;- curScreenY;
- X if (curScreenX - newScreenX == 0 && curScreenY - newScreenY == 0)
- X doConfigOneWindow(win, mstuff);
- X else GroupApply(leader->groupid, configOneClient, mstuff,
- X GROUP_LEADER | GROUP_DEPENDENT);
- X }
- X else doConfigOneWindow(win, mstuff);
- X return (void *) 0;
- X}
- X
- Xstatic void *
- XdoConfigOneClientCleanup(cli)
- X Client *cli;
- X
- X{
- X cli->flags &= ~CLMoved;
- X return (void *) 0;
- X}
- X
- Xstatic void *
- XconfigOneWindowCleanup(win)
- X WinGeneric *win;
- X{
- XClient *leader;
- X
- X if (GRV.VirtualMoveGroups) {
- X leader = GroupLeader(win->core.client->groupid);
- X if (!leader) {
- X doConfigOneClientCleanup(win->core.client);
- X return (void *) 0;
- X }
- X GroupApply(leader->groupid, doConfigOneClientCleanup, 0,
- X GROUP_LEADER | GROUP_DEPENDENT);
- X }
- X else win->core.client->flags &= ~CLMoved;
- X return (void *) 0;
- X}
- X
- X/*
- X * moveDone
- X *
- X * Cleanup function for window moving. Releases grabs, uninstalls
- X * interposition, cleans up.
- X */
- Xstatic void
- XmoveDone(mstuff)
- X MoveClosure *mstuff;
- X{
- X /*
- X * If we're dragging the outlines, we must ungrab the server and undraw
- X * the last set of boxes.
- X */
- X if (!mstuff->dragwin) {
- X (void) ListApply(mstuff->winlist, drawOneBox, mstuff);
- X XUngrabServer(mstuff->dpy);
- X }
- X UninstallInterposer();
- X XUngrabPointer(mstuff->dpy, CurrentTime);
- X XUngrabKeyboard(mstuff->dpy, CurrentTime);
- X
- X (void) ListApply(mstuff->winlist, configOneWindow, mstuff);
- X (void) ListApply(mstuff->winlist, configOneWindowCleanup, 0);
- X ListDestroy(mstuff->winlist);
- X if (mstuff->region) {
- X XDestroyRegion(mstuff->region);
- X if (mstuff->num_children)
- X XFree(mstuff->children);
- X }
- X
- X destroyStatusWindow(mstuff->statuswindow);
- X GRV.AutoRaise = mstuff->AutoRaise;
- X}
- X
- X
- X/* ===== mouse-based resizing ============================================= */
- X
- X
- X/*
- X * Note on use of gravity values: in this section, the gravity field is used
- X * to denote the window edge or corner that is being moved. It's not
- X * being used as "gravity" in the usual sense, which is the location that is
- X * being held constant.
- X *
- X * TODO:
- X * (1) implement screen edge hysteresis for resize+move mode (meta key);
- X * (2) implement window edge hysteresis.
- X */
- X
- X/*
- X * The following enum is arranged specifically so that the values can be
- X * tested with bit operations. The one-bit indicates down or right if one, up
- X * or left if zero. The two-bit indicates vertical if one, horizontal if zero.
- X * The four-bit indicates a jump if one, normal if zero.
- X */
- Xtypedef enum {
- X RS_LEFT = 0,
- X RS_RIGHT,
- X RS_UP,
- X RS_DOWN,
- X RS_J_LEFT,
- X RS_J_RIGHT,
- X RS_J_UP,
- X RS_J_DOWN
- X} ResizeAction;
- X
- X#define RS_ISRIGHT (1<<0)
- X#define RS_ISDOWN (1<<0)
- X#define RS_ISVERT (1<<1)
- X#define RS_ISJUMP (1<<2)
- X
- X#define RS_JUMPMULT 10 /* jump multiplier */
- X
- Xstruct {
- X int x, y;
- X} ResizeDeltas[] = {
- X { -1, 0 }, /* left */
- X { 1, 0 }, /* right */
- X { 0, -1 }, /* up */
- X { 0, 1 }, /* down */
- X { -RS_JUMPMULT, 0 }, /* jump left */
- X { RS_JUMPMULT, 0 }, /* jump right */
- X { 0, -RS_JUMPMULT }, /* jump up */
- X { 0, RS_JUMPMULT } /* jump down */
- X};
- X
- X
- Xtypedef struct {
- X Client *cli;
- X Constraint constraint;
- X Bool drawn;
- X Bool moving;
- X Bool minAspect, maxAspect;
- X Bool baseProvided;
- X int origX, origY;
- X int curX, curY; /* current mouse position */
- X int winX, winY; /* current window position */
- X int winW, winH; /* current window height */
- X int minW, minH;
- X int maxW, maxH;
- X int incW, incH;
- X int minAspectX, minAspectY;
- X int maxAspectX, maxAspectY;
- X int baseW, baseH;
- X int borderW, borderH; /* size of frame border */
- X void (*callback)();
- X void *cbarg;
- X StatusWinInfo *statuswindow;
- X int gravity; /* see note above */
- X Bool mouse; /* using mouse? */
- X} ResizeClosure;
- X
- X
- X/*
- X * Macro for adjusting the size of a window to its resize increment. First,
- X * assigns diff to be the difference between the size and the next lesser
- X * incremental size. If diff is greater than half the incremental
- X * size, adjust the size upward to the next greater increment, otherwise
- X * adjust downward. THIS MACRO ALTERS ITS FIRST ARGUMENT.
- X *
- X * size is the window size to be adjusted
- X * base is base size, to be subtracted off before modulo is done
- X * i is the incremental size
- X */
- X#define INCADJ(size, base, i) \
- X { \
- X int diff; \
- X diff = ((size) - (base)) % (i); \
- X (size) += (diff > (i)/2) ? (i)-diff : -diff; \
- X }
- X
- X
- Xstatic void
- XresizeDraw(rstuff)
- X ResizeClosure *rstuff;
- X{
- X drawDouble(rstuff->cli->dpy, WinRootID(rstuff->cli->framewin),
- X WinGC(rstuff->cli->framewin, ROOT_GC),
- X rstuff->winX, rstuff->winY, rstuff->winW, rstuff->winH);
- X drawDouble(rstuff->cli->dpy,
- X PANEWINOFCLIENT(rstuff->cli->scrInfo->vdm->client),
- X WinGC(rstuff->cli->framewin, ROOT_GC),
- X rstuff->winX / rstuff->cli->scrInfo->vdm->resources->scale,
- X rstuff->winY / rstuff->cli->scrInfo->vdm->resources->scale,
- X rstuff->winW / rstuff->cli->scrInfo->vdm->resources->scale,
- X rstuff->winH / rstuff->cli->scrInfo->vdm->resources->scale);
- X}
- X
- X
- Xstatic void
- XresizePaintStatus(rstuff)
- X ResizeClosure *rstuff;
- X{
- X char buf[30];
- X int w, h;
- X
- X w = rstuff->winW - rstuff->borderW;
- X h = rstuff->winH - rstuff->borderH;
- X
- X if (rstuff->baseProvided) {
- X w -= rstuff->baseW;
- X h -= rstuff->baseH;
- X }
- X
- X sprintf(buf, gettext("size: %d x %d"), w / rstuff->incW, h / rstuff->incH);
- X paintStatusWindow(rstuff->statuswindow, buf);
- X}
- X
- X
- Xstatic void
- XresizeDone(dpy, e, w, rstuff, doit)
- X Display *dpy;
- X XEvent *e;
- X WinGeneric *w;
- X ResizeClosure *rstuff;
- X Bool doit;
- X{
- X if (rstuff->drawn)
- X resizeDraw(rstuff);
- X
- X UninstallInterposer();
- X XUngrabPointer(dpy, e->xbutton.time);
- X XUngrabKeyboard(dpy, e->xbutton.time);
- X XUngrabServer(dpy);
- X
- X if (doit)
- X GFrameSetConfig(rstuff->cli->framewin, rstuff->winX, rstuff->winY,
- X rstuff->winW, rstuff->winH);
- X
- X if (rstuff->callback != NULL)
- X (*rstuff->callback)(dpy, rstuff->cbarg);
- X
- X destroyStatusWindow(rstuff->statuswindow);
- X}
- X
- X
- Xstatic void
- XresizeMotion(rstuff, x, y)
- X ResizeClosure *rstuff;
- X int x, y;
- X{
- X int dx, dy, dW, dH, newW, newH;
- X
- X dx = x - rstuff->curX;
- X dy = y - rstuff->curY;
- X
- X if (ABS(dx) <= GRV.MoveThreshold && ABS(dy) <= GRV.MoveThreshold &&
- X !rstuff->drawn)
- X return;
- X
- X if (rstuff->mouse) {
- X if (rstuff->constraint == EitherConstrained) {
- X if (ABS(rstuff->origX - x) > ABS(rstuff->origY - y))
- X rstuff->constraint = HorizConstrained;
- X else
- X rstuff->constraint = VertConstrained;
- X }
- X
- X if (rstuff->constraint == HorizConstrained) {
- X y = rstuff->origY;
- X dy = y - rstuff->curY;
- X } else if (rstuff->constraint == VertConstrained) {
- X x = rstuff->origX;
- X dx = x - rstuff->curX;
- X }
- X }
- X
- X newW = rstuff->winW;
- X newH = rstuff->winH;
- X if (rstuff->moving) {
- X if (dx == 0 && dy == 0)
- X return;
- X if (rstuff->drawn)
- X resizeDraw(rstuff);
- X rstuff->winX += dx;
- X rstuff->winY += dy;
- X rstuff->curX += dx;
- X rstuff->curY += dy;
- X resizeDraw(rstuff);
- X rstuff->drawn = True;
- X return;
- X }
- X
- X switch (rstuff->gravity) {
- X case NorthWestGravity:
- X newW -= dx;
- X newH -= dy;
- X break;
- X case NorthGravity:
- X newH -= dy;
- X break;
- X case NorthEastGravity:
- X newW += dx;
- X newH -= dy;
- X break;
- X case WestGravity:
- X newW -= dx;
- X break;
- X case CenterGravity:
- X break;
- X case EastGravity:
- X newW += dx;
- X break;
- X case SouthWestGravity:
- X newW -= dx;
- X newH += dy;
- X break;
- X case SouthGravity:
- X newH += dy;
- X break;
- X case SouthEastGravity:
- X newW += dx;
- X newH += dy;
- X break;
- X }
- X
- X /*
- X * Convert from frame size to pane size, apply the constraints, then
- X * convert back to frame size.
- X */
- X
- X newW -= rstuff->borderW;
- X newH -= rstuff->borderH;
- X
- X INCADJ(newW, rstuff->baseW, rstuff->incW);
- X INCADJ(newH, rstuff->baseH, rstuff->incH);
- X
- X newW = MAX(rstuff->minW, MIN(rstuff->maxW, newW));
- X newH = MAX(rstuff->minH, MIN(rstuff->maxH, newH));
- X
- X if (rstuff->maxAspect &&
- X newW * rstuff->maxAspectY > newH * rstuff->maxAspectX)
- X {
- X if (rstuff->maxAspectX > rstuff->maxAspectY) {
- X /* max aspect is wider than tall; increase height. */
- X newH = (newW * rstuff->maxAspectY) / rstuff->maxAspectX;
- X if (newH > rstuff->maxH) {
- X newH = rstuff->maxH;
- X newW = (newH * rstuff->maxAspectX) / rstuff->maxAspectY;
- X }
- X } else {
- X /* max aspect is taller than wide; decrease width. */
- X newW = (newH * rstuff->maxAspectX) / rstuff->maxAspectY;
- X if (newW < rstuff->minW) {
- X newW = rstuff->minW;
- X newH = (newW * rstuff->maxAspectY) / rstuff->maxAspectX;
- X }
- X }
- X }
- X
- X if (rstuff->minAspect &&
- X newW * rstuff->minAspectY < newH * rstuff->minAspectX)
- X {
- X if (rstuff->minAspectX > rstuff->minAspectY) {
- X /* min aspect is wider than tall; decrease height. */
- X newH = (newW * rstuff->minAspectY) / rstuff->minAspectX;
- X if (newH < rstuff->minH) {
- X newH = rstuff->minH;
- X newW = (newH * rstuff->minAspectX) / rstuff->minAspectY;
- X }
- X } else {
- X /* min aspect is taller than wide; increase width. */
- X newW = (newH * rstuff->minAspectX) / rstuff->minAspectY;
- X if (newW > rstuff->maxW) {
- X newW = rstuff->maxW;
- X newH = (newW * rstuff->minAspectY) / rstuff->minAspectX;
- X }
- X }
- X }
- X
- X newW += rstuff->borderW;
- X newH += rstuff->borderH;
- X
- X /*
- X * Calculate the change in size (if any) and update the window's origin
- X * (winX, winY) depending on which corner is being moved. Also, update
- X * the virtual pointer location (curX, curY). Don't draw anything if the
- X * size hasn't changed.
- X */
- X
- X dW = newW - rstuff->winW;
- X dH = newH - rstuff->winH;
- X
- X if (dW == 0 && dH == 0)
- X return;
- X
- X if (rstuff->drawn)
- X resizeDraw(rstuff);
- X
- X switch (rstuff->gravity) {
- X case NorthWestGravity:
- X rstuff->winX -= dW;
- X rstuff->winY -= dH;
- X rstuff->curX -= dW;
- X rstuff->curY -= dH;
- X break;
- X case NorthGravity:
- X rstuff->winX -= dW / 2;
- X rstuff->winY -= dH;
- X rstuff->curY -= dH;
- X break;
- X case NorthEastGravity:
- X rstuff->winY -= dH;
- X rstuff->curX += dW;
- X rstuff->curY -= dH;
- X break;
- X case WestGravity:
- X rstuff->winX -= dW;
- X rstuff->winY -= dH / 2;
- X rstuff->curX -= dW;
- X break;
- X case CenterGravity:
- X rstuff->winX -= dW / 2;
- X rstuff->winY -= dH / 2;
- X break;
- X case EastGravity:
- X rstuff->winY -= dH / 2;
- X rstuff->curX += dW;
- X break;
- X case SouthWestGravity:
- X rstuff->winX -= dW;
- X rstuff->curX -= dW;
- X rstuff->curY += dH;
- X break;
- X case SouthGravity:
- X rstuff->winX -= dW / 2;
- X rstuff->curY += dH;
- X break;
- X case SouthEastGravity:
- X rstuff->curX += dW;
- X rstuff->curY += dH;
- X break;
- X }
- X
- X rstuff->winW = newW;
- X rstuff->winH = newH;
- X
- X resizeDraw(rstuff);
- X resizePaintStatus(rstuff);
- X rstuff->drawn = True;
- X}
- X
- X
- Xvoid
- XresizeDelta(rstuff, action)
- X ResizeClosure *rstuff;
- X ResizeAction action;
- X{
- X int dx, dy;
- X
- X if (rstuff->mouse)
- X return;
- X
- X if (action & RS_ISVERT) {
- X switch (rstuff->gravity) {
- X case WestGravity:
- X case CenterGravity:
- X case EastGravity:
- X rstuff->gravity += (action & RS_ISDOWN) ? 3 : -3;
- X break;
- X }
- X } else {
- X switch (rstuff->gravity) {
- X case NorthGravity:
- X case CenterGravity:
- X case SouthGravity:
- X rstuff->gravity += (action & RS_ISRIGHT) ? 1 : -1;
- X break;
- X }
- X }
- X
- X /* generate a delta vector based on which edge is being moved */
- X
- X dx = ResizeDeltas[action].x;
- X dy = ResizeDeltas[action].y;
- X
- X dx *= rstuff->incW;
- X dy *= rstuff->incH;
- X
- X resizeMotion(rstuff, rstuff->curX + dx, rstuff->curY + dy);
- X}
- X
- X
- Xstatic int
- XresizeInterposer(dpy, e, w, rstuff)
- X Display *dpy;
- X XEvent *e;
- X WinGeneric *w;
- X ResizeClosure *rstuff;
- X{
- X int dx, dy;
- X unsigned int mask;
- X SemanticAction action;
- X
- X switch (e->type) {
- X case ButtonPress:
- X if (!FirstButtonDown(e))
- X break;
- X switch (ResolveMouseBinding(dpy, e,
- X ModMaskMap[MOD_CONSTRAIN] | ModMaskMap[MOD_INVERT]))
- X {
- X case ACTION_SELECT:
- X rstuff->mouse = True;
- X rstuff->curX = rstuff->origX = e->xbutton.x_root;
- X rstuff->curY = rstuff->origY = e->xbutton.y_root;
- X if (e->xbutton.state & ModMaskMap[MOD_CONSTRAIN])
- X rstuff->constraint = EitherConstrained;
- X if (e->xbutton.state & ModMaskMap[MOD_INVERT])
- X rstuff->moving = True;
- X
- X rstuff->gravity = NorthWestGravity;
- X if (e->xbutton.y_root > rstuff->winY + (rstuff->winH / 2))
- X rstuff->gravity = SouthWestGravity;
- X if (e->xbutton.x_root > rstuff->winX + (rstuff->winW / 2))
- X rstuff->gravity += 2; /* turns any west into any east */
- X
- X resizeMotion(rstuff, e->xbutton.x_root, e->xbutton.y_root);
- X break;
- X default:
- X resizeDone(dpy, e, w, rstuff, False);
- X break;
- X }
- X break;
- X
- X case ButtonRelease:
- X if (AllButtonsUp(e))
- X resizeDone(dpy, e, w, rstuff, True);
- X break;
- X
- X case MotionNotify:
- X if (e->xmotion.same_screen && rstuff->mouse)
- X resizeMotion(rstuff, e->xmotion.x_root, e->xmotion.y_root);
- X break;
- X
- X case KeyPress:
- X action = FindKeyboardAction(dpy, e);
- X
- X switch (action) {
- X
- X case ACTION_STOP:
- X resizeDone(dpy, e, w, rstuff, False);
- X break;
- X
- X case ACTION_UP: resizeDelta(rstuff, RS_UP); break;
- X case ACTION_DOWN: resizeDelta(rstuff, RS_DOWN); break;
- X case ACTION_LEFT: resizeDelta(rstuff, RS_LEFT); break;
- X case ACTION_RIGHT: resizeDelta(rstuff, RS_RIGHT); break;
- X case ACTION_JUMP_UP: resizeDelta(rstuff, RS_J_UP); break;
- X case ACTION_JUMP_DOWN: resizeDelta(rstuff, RS_J_DOWN); break;
- X case ACTION_JUMP_LEFT: resizeDelta(rstuff, RS_J_LEFT); break;
- X case ACTION_JUMP_RIGHT: resizeDelta(rstuff, RS_J_RIGHT); break;
- X
- X case ACTION_EXEC_DEFAULT:
- X resizeDone(dpy, e, w, rstuff, True);
- X break;
- X
- X default:
- X mask = FindModifierMask(e->xkey.keycode);
- X if (mask == ModMaskMap[MOD_CONSTRAIN] && rstuff->mouse) {
- X rstuff->constraint = EitherConstrained;
- X resizeMotion(rstuff, e->xkey.x_root, e->xkey.y_root);
- X } else if (mask == ModMaskMap[MOD_INVERT]) {
- X rstuff->moving = True;
- X } else {
- X KeyBeep(dpy, e);
- X }
- X break;
- X }
- X break;
- X
- X case KeyRelease:
- X mask = FindModifierMask(e->xkey.keycode);
- X if (mask == ModMaskMap[MOD_CONSTRAIN] && rstuff->mouse) {
- X rstuff->constraint = Unconstrained;
- X resizeMotion(rstuff, e->xkey.x_root, e->xkey.y_root);
- X } else if (mask == ModMaskMap[MOD_INVERT])
- X rstuff->moving = False;
- X break;
- X
- X case Expose:
- X return DISPOSE_DISPATCH;
- X
- X default:
- X return DISPOSE_DEFER;
- X }
- X
- X return DISPOSE_USED;
- X}
- X
- X
- X
- X/*
- X * Install an interposer for resizing with the mouse.
- X */
- Xvoid
- XUserResizeWin(cli, trigger, corner, callback, cbarg)
- X Client *cli;
- X XEvent *trigger;
- X WhichResize corner;
- X void (*callback)();
- X void *cbarg;
- X{
- X static ResizeClosure rstuff;
- X XSizeHints *sh = cli->normHints;
- X Window root = WinRootID(cli->framewin);
- X Time timestamp;
- X int frameMinWidth, frameMinHeight;
- X
- X if (trigger == NULL || trigger->type == KeyPress) {
- X if (trigger == NULL)
- X timestamp = CurrentTime;
- X else
- X timestamp = trigger->xkey.time;
- X rstuff.mouse = False;
- X rstuff.origX = rstuff.curX = cli->framewin->core.x;
- X rstuff.origY = rstuff.curY = cli->framewin->core.y;
- X } else {
- X /* it's a button press */
- X timestamp = trigger->xbutton.time;
- X rstuff.mouse = True;
- X if (trigger->xbutton.state & ModMaskMap[MOD_CONSTRAIN])
- X rstuff.constraint = EitherConstrained;
- X else
- X rstuff.constraint = Unconstrained;
- X
- X if (trigger->xbutton.state & ModMaskMap[MOD_INVERT])
- X rstuff.moving = True;
- X else
- X rstuff.moving = False;
- X rstuff.origX = rstuff.curX = trigger->xbutton.x_root;
- X rstuff.origY = rstuff.curY = trigger->xbutton.y_root;
- X }
- X
- X switch (corner) {
- X case upleft: rstuff.gravity = NorthWestGravity; break;
- X case upright: rstuff.gravity = NorthEastGravity; break;
- X case lowleft: rstuff.gravity = SouthWestGravity; break;
- X case lowright: rstuff.gravity = SouthEastGravity; break;
- X case keyevent: rstuff.gravity = CenterGravity; break;
- X }
- X
- X /* Grab the pointer to change the cursor and confine to the root window. */
- X if (XGrabPointer(cli->dpy, root, True,
- X ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
- X GrabModeAsync, GrabModeAsync, root,
- X GRV.ResizePointer, timestamp) != GrabSuccess)
- X {
- X ErrorWarning(gettext("failed to grab pointer"));
- X return;
- X }
- X
- X if (XGrabKeyboard(cli->dpy, root, False,
- X GrabModeAsync, GrabModeAsync,
- X timestamp) != GrabSuccess)
- X {
- X /* note: not fatal */
- X ErrorWarning(gettext("failed to grab keyboard"));
- X }
- X
- X XGrabServer(cli->dpy);
- X
- X /* Fill in the closure for the interposer. */
- X
- X rstuff.drawn = False;
- X rstuff.cli = cli;
- X rstuff.winX = cli->framewin->core.x;
- X rstuff.winY = cli->framewin->core.y;
- X rstuff.winW = cli->framewin->core.width;
- X rstuff.winH = cli->framewin->core.height;
- X
- X rstuff.callback = callback;
- X rstuff.cbarg = cbarg;
- X
- X /*
- X * Look at the client's size hints and update the closure appropriately.
- X */
- X
- X rstuff.minW = rstuff.minH = 1;
- X rstuff.maxW = rstuff.maxH = 32767; /* REMIND: max value of signed short */
- X rstuff.incW = rstuff.incH = 1;
- X rstuff.minAspect = rstuff.maxAspect = False;
- X rstuff.baseW = rstuff.baseH = 0;
- X
- X if (sh != NULL) {
- X if (sh->flags & PMinSize) {
- X rstuff.minW = sh->min_width;
- X rstuff.minH = sh->min_height;
- X } else if (sh->flags & PBaseSize) {
- X rstuff.minW = MAX(1,sh->base_width);
- X rstuff.minH = MAX(1,sh->base_height);
- X }
- X
- X if (sh->flags & PMaxSize) {
- X rstuff.maxW = sh->max_width;
- X rstuff.maxH = sh->max_height;
- X }
- X
- X if ((sh->flags & PResizeInc) &&
- X sh->width_inc > 0 && sh->height_inc > 0)
- X {
- X rstuff.incW = sh->width_inc;
- X rstuff.incH = sh->height_inc;
- X }
- X
- X if (sh->flags & PAspect) {
- X if (sh->min_aspect.x > 0 && sh->min_aspect.y > 0) {
- X rstuff.minAspect = True;
- X rstuff.minAspectX = sh->min_aspect.x;
- X rstuff.minAspectY = sh->min_aspect.y;
- X }
- X if (sh->max_aspect.x > 0 && sh->max_aspect.y > 0) {
- X rstuff.maxAspect = True;
- X rstuff.maxAspectX = sh->max_aspect.x;
- X rstuff.maxAspectY = sh->max_aspect.y;
- X }
- X }
- X
- X if (sh->flags & PBaseSize) {
- X rstuff.baseW = sh->base_width;
- X rstuff.baseH = sh->base_height;
- X rstuff.baseProvided = True;
- X } else if (sh->flags & PMinSize) {
- X rstuff.baseW = sh->min_width;
- X rstuff.baseH = sh->min_height;
- X rstuff.baseProvided = False;
- X }
- X }
- X
- X /* figure in the size of the frame decorations */
- X
- X rstuff.borderW
- X = FrameWidthLeft(cli->framewin) + FrameWidthRight(cli->framewin);
- X rstuff.borderH
- X = FrameHeightTop(cli->framewin) + FrameHeightBottom(cli->framewin);
- X
- X FrameMinSize(cli->framewin, &frameMinWidth, &frameMinHeight);
- X frameMinWidth -= rstuff.borderW;
- X frameMinHeight -= rstuff.borderH;
- X rstuff.minW = MAX(rstuff.minW, frameMinWidth);
- X rstuff.minH = MAX(rstuff.minH, frameMinHeight);
- X
- X /* map the geom window and draw the initial outline, if necessary */
- X
- X if (GRV.ShowResizeGeometry)
- X rstuff.statuswindow = createStatusWindow(cli->dpy, cli->scrInfo,
- X gettext("size: 0000 x 0000"));
- X else
- X rstuff.statuswindow = NULL;
- X
- X if (trigger == NULL || trigger->type == KeyPress) {
- X resizeDraw(rstuff);
- X rstuff.drawn = True;
- X }
- X
- X resizePaintStatus(&rstuff);
- X
- X InstallInterposer(resizeInterposer, &rstuff);
- X}
- X
- X
- X/* ===== root bounding box ================================================ */
- X
- X
- Xtypedef struct _rootboxclosure {
- X int x0, y0;
- X int x, y;
- X unsigned int w, h;
- X WinRoot *rootWin;
- X Window rootID;
- X GC rootGC;
- X void *closure;
- X void (*callback)();
- X} RootBoxClosure;
- X
- X
- Xstatic int
- XrootBoxInterposer(dpy, event, w, rbc)
- X Display *dpy;
- X XEvent *event;
- X WinGeneric *w;
- X RootBoxClosure *rbc;
- X{
- X XEvent nextevent;
- X register int ex, ey;
- X
- X switch (event->type) {
- X
- X case ButtonPress:
- X return DISPOSE_USED;
- X
- X case MotionNotify:
- X /* if the event is off the screen, ignore it */
- X if (event->xmotion.root != rbc->rootID)
- X return DISPOSE_USED;
- X
- X /*
- X * Motion compression. If the next event is a MotionNotify,
- X * ignore this one.
- X */
- X if (XEventsQueued(dpy, QueuedAfterReading) > 0 &&
- X (XPeekEvent(dpy, &nextevent), nextevent.type == MotionNotify))
- X {
- X return DISPOSE_USED;
- X }
- X
- X /* erase old box */
- X drawDouble(dpy, rbc->rootID, rbc->rootGC,
- X rbc->x, rbc->y, rbc->w, rbc->h);
- X
- X /* update closure with new position */
- X
- X ex = event->xmotion.x_root;
- X ey = event->xmotion.y_root;
- X
- X if (ex > rbc->x0) {
- X rbc->x = rbc->x0;
- X rbc->w = ex - rbc->x;
- X } else {
- X rbc->x = ex;
- X rbc->w = rbc->x0 - rbc->x;
- X }
- X
- X if (ey > rbc->y0) {
- X rbc->y = rbc->y0;
- X rbc->h = ey - rbc->y;
- X } else {
- X rbc->y = ey;
- X rbc->h = rbc->y0 - rbc->y;
- X }
- X
- X /* draw new box */
- X
- X drawDouble(dpy, rbc->rootID, rbc->rootGC,
- X rbc->x, rbc->y, rbc->w, rbc->h);
- X return DISPOSE_USED;
- X
- X case ButtonRelease:
- X if (!AllButtonsUp(event))
- X return DISPOSE_USED;
- X break;
- X
- X case KeyPress:
- X if (FindKeyboardAction(dpy, event) != ACTION_STOP) {
- X KeyBeep(dpy,event);
- X return DISPOSE_USED;
- X }
- X break;
- X
- X default:
- X return DISPOSE_DEFER;
- X }
- X
- X /*
- X * erase outline, let go of server, call the callback
- X */
- X drawDouble(dpy, rbc->rootID, rbc->rootGC,
- X rbc->x, rbc->y, rbc->w, rbc->h);
- X
- X XUngrabServer(dpy);
- X XUngrabPointer(dpy, CurrentTime);
- X XUngrabKeyboard(dpy, CurrentTime);
- X
- X UninstallInterposer();
- X
- X (*rbc->callback)(dpy, rbc->rootWin, rbc->x, rbc->y, rbc->w, rbc->h,
- X event->xbutton.time, rbc->closure);
- X
- X return DISPOSE_USED;
- X}
- X
- X
- X/*
- X * TraceRootBox -- trace an XOR box with the initial point specified
- X * by pEvent, which is assumed to be a ButtonPress event. Call the
- X * callback function when done.
- X */
- Xvoid
- XTraceRootBox(dpy, winInfo, pEvent, callback, closure)
- XDisplay *dpy;
- XWinRoot *winInfo;
- XXEvent *pEvent;
- Xvoid (*callback)();
- Xvoid *closure;
- X{
- X static RootBoxClosure rbc;
- X Window rootID = WinRootID(winInfo);
- X
- X /* Change and confine the cursor. */
- X if (XGrabPointer(dpy, rootID, True,
- X ButtonReleaseMask | PointerMotionMask,
- X GrabModeAsync, GrabModeAsync, rootID, GRV.BasicPointer,
- X pEvent->xbutton.time) != GrabSuccess)
- X {
- X ErrorWarning(gettext("failed to grab pointer"));
- X return;
- X }
- X
- X if (XGrabKeyboard(dpy, rootID, False, GrabModeAsync, GrabModeAsync,
- X pEvent->xbutton.time) != GrabSuccess)
- X {
- X /* note: not fatal */
- X ErrorWarning(gettext("failed to grab keyboard"));
- X }
- X
- X rbc.x = rbc.x0 = pEvent->xbutton.x_root;
- X rbc.y = rbc.y0 = pEvent->xbutton.y_root;
- X rbc.w = rbc.h = 0;
- X rbc.rootWin = winInfo;
- X rbc.rootID = rootID;
- X rbc.rootGC = WinGC(winInfo, ROOT_GC);
- X rbc.callback = callback;
- X rbc.closure = closure;
- X
- X /* Grab the server, then draw the initial outline. */
- X XGrabServer(dpy);
- X drawDouble(dpy, rootID, WinGC(winInfo, ROOT_GC),
- X rbc.x, rbc.y, 0, 0);
- X
- X InstallInterposer(rootBoxInterposer, &rbc);
- X return;
- X}
- END_OF_FILE
- if test 48613 -ne `wc -c <'moveresize.c'`; then
- echo shar: \"'moveresize.c'\" unpacked with wrong size!
- fi
- # end of 'moveresize.c'
- fi
- echo shar: End of archive 4 \(of 21\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 21 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Molecular Simulations, Inc. mail: dcmartin@postgres.berkeley.edu
- 796 N. Pastoria Avenue uucp: uwvax!ucbvax!dcmartin
- Sunnyvale, California 94086 at&t: 408/522-9236
-